﻿Option Strict Off 'This is needed for the late binding
Imports NewHeaderSystems.Archive.Data
Imports NewHeaderSystems.Archive.Core
Imports NewHeaderSystems.Archive.Engine

''' <summary>
''' This page allows the user to view all unassigned confirms and then use the edit pane to fill in the
''' missing information and archive the confirms.
''' </summary>
Public Class FinishArchiving
    Inherits PageTemplate

#Region "Constants & Enums"
    Private Enum GridColumn
        ID = 1
        Print
        AccountID
        CustodianID
        Ticker
        Cusip
    End Enum


#End Region

#Region "Properties & Member Variables"
    Private _accountsList As List(Of AccountView)
    Private _securitiesList As List(Of SecurityView)

    ''' <summary>
    ''' CanEnter loads the data the first time so that on PageEnter we don't need to load again.
    ''' </summary>
    Private _startupGridData As List(Of ConfirmView)

    'The list of confirms to load. This is set when the user comes from the StartArchiving page.
    Private Shared _archiveHistoryList As List(Of String)

    ''' <summary>
    ''' Gets or sets the list of ArchiveHistory ID's. Only confirms from this ArchiveHistory run are displayed.
    ''' </summary>
    ''' <value>The archive history list.</value>
    Public Shared Property ArchiveHistoryList() As List(Of String)
        Get
            Return _archiveHistoryList
        End Get
        Set(ByVal value As List(Of String))
            _archiveHistoryList = value
        End Set
    End Property

    ''' <summary>
    ''' Gets the current confirm.
    ''' </summary>
    ''' <value>The current confirm.</value>
    Private ReadOnly Property CurrentConfirm() As ConfirmView
        Get
            Return DirectCast(confirmsGrid.Rows(confirmsGrid.SelectedRows(0).Index).DataBoundItem, ConfirmView)
        End Get
    End Property
#End Region

#Region "Page Methods"
    ''' <summary>
    ''' Handles the Load event of the ProcessUnassigned control.
    ''' </summary>
    ''' <param name="sender">The source of the event.</param>
    ''' <param name="e">The <see cref="System.EventArgs" /> instance containing the event data.</param>
    Private Sub ProcessUnassigned_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Title = "Finish Archiving"
        Description = "Process the confirms that have not yet been assigned."
        PageIcon = My.Resources.Control_Panel
    End Sub

    ''' <summary>
    ''' Determines whether this instance can enter the specified view state.
    ''' </summary>
    ''' <param name="viewState">State of the view.</param>
    ''' <returns>
    ''' <c>true</c> if this instance can enter the specified view state; otherwise, <c>false</c>.
    ''' </returns>
    Public Overrides Function CanEnter(ByVal viewState As Microsoft.Samples.Windows.Forms.Navigation.ViewState) As Boolean
        _startupGridData = GetGridData()
        Dim canEnterPage = _startupGridData.Count <> 0
        If Not canEnterPage Then
            MessageBox.Show("There are no unassigned confirms.", "Finish Archiving", MessageBoxButtons.OK, MessageBoxIcon.Information)
        End If
        Return canEnterPage
    End Function

    ''' <summary>
    ''' Handles the PageEnter event of the FinishArchiving control.
    ''' </summary>
    ''' <param name="sender">The source of the event.</param>
    ''' <param name="e">The <see cref="Microsoft.Samples.Windows.Forms.Navigation.PageEventArgs" /> instance containing the event data.</param>
    Private Sub FinishArchiving_PageEnter(ByVal sender As System.Object, ByVal e As Microsoft.Samples.Windows.Forms.Navigation.PageEventArgs) Handles MyBase.PageEnter
        LoadGrid(_startupGridData) 'CanEnter would have loaded the data.
    End Sub

    ''' <summary>
    ''' Handles the Leave event of the FinishArchiving control.
    ''' </summary>
    ''' <param name="sender">The source of the event.</param>
    ''' <param name="e">The <see cref="System.EventArgs" /> instance containing the event data.</param>
    Private Sub FinishArchiving_Leave(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Leave
        'Clear the history list so that when user enters from home page we show all unassigned confirms.
        _archiveHistoryList = Nothing
    End Sub

#End Region

#Region "Grid Methods"
    ''' <summary>
    ''' Gets the grid data.
    ''' </summary>
    ''' <returns></returns>
    Private Function GetGridData() As List(Of ConfirmView)
        Dim totalRowCount As Integer
        Return DataScript.GetSearchResults(False, Nothing, Nothing, _
                                            False, Nothing, Nothing, _
                                            "", "", "", "", _
                                            "", "", "", "", True, _archiveHistoryList, DataScript.ALL_ROWS, totalRowCount)

    End Function

    ''' <summary>
    ''' Loads the grid.
    ''' </summary>
    ''' <param name="confirmsView">The confirms view.</param>
    ''' <returns></returns>
    Private Function LoadGrid(ByVal confirmsView As List(Of ConfirmView)) As Integer
        Me.ParentForm.Cursor = Cursors.WaitCursor
        Dim bs As New BindingSource
        bs.DataSource = New SortableBindingList(Of ConfirmView)(confirmsView)
        confirmsGrid.DataSource = bs

        ShowSummary()

        Me.ParentForm.Cursor = Cursors.Default
        Return confirmsView.Count
    End Function

    ''' <summary>
    ''' Syncs the grid.
    ''' </summary>
    Private Sub SyncGrid()
        Dim confirmsView = GetGridData()
        LoadGrid(confirmsView)

        If confirmsView.Count = 0 Then
            MessageBox.Show("All unassigned confirms have been archived successfully. There are no more unassigned confirms.", "Finish Archiving", MessageBoxButtons.OK, MessageBoxIcon.Information)
            GoHome()
        End If

    End Sub

    ''' <summary>
    ''' Shows the summary.
    ''' </summary>
    Private Sub ShowSummary()
        Dim message As String
        Dim resultCount As Integer = Aggregate p In confirmsGrid.Rows Where p.Visible = True Into Count()

        If resultCount = 0 Then
            message = "There are no more unassigned confirms."
        Else
            message = String.Format("{0} unassigned confirms remaining.", resultCount)
        End If
        lblResultSummary.Text = message
        lblResultSummary.Visible = True
    End Sub

    ''' <summary>
    ''' Shows the confirm.
    ''' </summary>
    ''' <param name="confirmID">The confirm ID.</param>
    Private Sub ShowConfirm(ByVal confirmID As Integer)
        Dim confirmCreator As New ConfirmRenderer
        txtConfirmViewer.Text = confirmCreator.Render(confirmID)
    End Sub

    ''' <summary>
    ''' Handles the SelectionChanged event of the confirmsGrid control.
    ''' </summary>
    ''' <param name="sender">The source of the event.</param>
    ''' <param name="e">The <see cref="System.EventArgs" /> instance containing the event data.</param>
    Private Sub confirmsGrid_SelectionChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles confirmsGrid.SelectionChanged
        Me.Cursor = Cursors.WaitCursor
        RefreshConfirmView()
        Me.Cursor = Cursors.Default
    End Sub
#End Region

#Region "Edit Panel: ComboBox Loading"
    ''' <summary>
    ''' Refreshes the confirm view.
    ''' </summary>
    Private Sub RefreshConfirmView()
        If confirmsGrid.SelectedRows.Count > 0 Then
            Dim confirm = CurrentConfirm()
            UpdateInputFields(confirm)
            ShowConfirm(confirm.ID)
        End If
    End Sub

    ''' <summary>
    ''' Updates the input fields.
    ''' </summary>
    ''' <param name="confirm">The confirm.</param>
    Private Sub UpdateInputFields(ByVal confirm As ConfirmView)

        'NOTE: Drop downs have to be loaded before setting values. If not setting the .Text value on ComboBox does not get displayed in the UI.
        LoadDropDowns(confirm)
        'NOTE:Call these in reverse order of display on screen so that when the form is shown first empty control has the focus.
        With confirm
            SetControlValue(cboCusip, .Cusip)
            SetControlValue(cboTicker, .TickerSymbol)
            SetControlValue(cboCustodianID, .CustodianAccountID)
            SetControlValue(cboAccountID, .AccountID)
        End With

    End Sub

    ''' <summary>
    ''' Sets the control value.
    ''' </summary>
    ''' <param name="control">The control.</param>
    ''' <param name="value">The value.</param>
    Private Sub SetControlValue(ByVal control As ComboBox, ByVal value As String)
        control.Text = value
        control.Enabled = String.IsNullOrEmpty(value)
        If control.Enabled Then control.Focus()
    End Sub

    ''' <summary>
    ''' Loads the drop downs.
    ''' </summary>
    ''' <param name="confirm">The confirm.</param>
    Private Sub LoadDropDowns(ByVal confirm As ConfirmView)
        LoadAccountDropDowns(confirm)
        LoadSecurityDropDowns(confirm)
    End Sub

    ''' <summary>
    ''' Loads the security drop downs.
    ''' </summary>
    ''' <param name="confirm">The confirm.</param>
    Private Sub LoadSecurityDropDowns(ByVal confirm As ConfirmView)
        'NOTE: Ideally we should use a local cache without pulling from the database each time.
        _securitiesList = DataScript.GetSecurities(confirm.TickerSymbol, confirm.Cusip, String.Empty)
        SetControlSyleAndData(cboTicker, _securitiesList, "Ticker")
        SetControlSyleAndData(cboCusip, _securitiesList, "Cusip")
    End Sub

    ''' <summary>
    ''' Loads the account drop downs.
    ''' </summary>
    ''' <param name="confirm">The confirm.</param>
    Private Sub LoadAccountDropDowns(ByVal confirm As ConfirmView)
        'NOTE: Ideally we should use a local cache without pulling from the database each time.
        _accountsList = DataScript.GetAccounts(confirm.AccountID, confirm.CustodianAccountID, String.Empty)
        SetControlSyleAndData(cboAccountID, _accountsList, "AccountID")
        SetControlSyleAndData(cboCustodianID, _accountsList, "CustodianID")
    End Sub

    ''' <summary>
    ''' Sets the control syle and data.
    ''' </summary>
    ''' <typeparam name="T"></typeparam>
    ''' <param name="cbo">The cbo.</param>
    ''' <param name="dataSource">The data source.</param>
    ''' <param name="displayMember">The display member.</param>
    Private Sub SetControlSyleAndData(Of T)(ByVal cbo As ComboBox, ByVal dataSource As List(Of T), ByVal displayMember As String)
        If cbo.Enabled Then
            cbo.DataSource = dataSource
            cbo.DisplayMember = displayMember
            cbo.ValueMember = displayMember
            cbo.SelectedIndex = -1 'Show the combo box as empty
            If dataSource.Count > 0 Then
                cbo.DropDownStyle = ComboBoxStyle.DropDown
            Else
                cbo.DropDownStyle = ComboBoxStyle.Simple
            End If

            'Since the two drop downs use the same datasource we need to switch off binding once data is loaded
            'If not when the user changes one drop-down the other one also changes
            Me.BindingContext(dataSource).SuspendBinding()
        Else
            cbo.DropDownStyle = ComboBoxStyle.Simple
        End If
    End Sub
#End Region

#Region "Button Event Handlers"
    ''' <summary>
    ''' Handles the Click event of the btnAddAccount control.
    ''' </summary>
    ''' <param name="sender">The source of the event.</param>
    ''' <param name="e">The <see cref="System.EventArgs" /> instance containing the event data.</param>
    Private Sub btnAddAccount_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAddAccount.Click
        Dim accountView As New AccountView With {.AccountID = cboAccountID.Text, .CustodianID = cboCustodianID.Text}
        Dim frm As New AccountMaintenanceEditor(accountView)
        If (frm.ShowDialog = DialogResult.OK) Then
            LoadAccountDropDowns(CurrentConfirm)
            With frm.AccountView
                If cboAccountID.Enabled Then cboAccountID.Text = frm.txtAccountID.Text
                If cboCustodianID.Enabled Then cboCustodianID.Text = frm.txtCustodianID.Text
            End With
        End If
    End Sub

    ''' <summary>
    ''' Handles the Click event of the btnAddSecurity control.
    ''' </summary>
    ''' <param name="sender">The source of the event.</param>
    ''' <param name="e">The <see cref="System.EventArgs" /> instance containing the event data.</param>
    Private Sub btnAddSecurity_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAddSecurity.Click
        Dim securityView As New SecurityView With {.Ticker = cboTicker.Text, .Cusip = cboCusip.Text}
        Dim frm As New SecurityMaintenanceEditor(securityView)
        If (frm.ShowDialog = DialogResult.OK) Then
            LoadSecurityDropDowns(CurrentConfirm)
            With frm.SecurityView
                If cboTicker.Enabled Then cboTicker.Text = frm.txtTicker.Text
                If cboCusip.Enabled Then cboCusip.Text = frm.txtCusip.Text
            End With
        End If
    End Sub

    ''' <summary>
    ''' Handles the Click event of the btnSaveAndNext control.
    ''' </summary>
    ''' <param name="sender">The source of the event.</param>
    ''' <param name="e">The <see cref="System.EventArgs" /> instance containing the event data.</param>
    Private Sub btnSaveAndNext_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSaveAndNext.Click
        DoSave()
    End Sub
#End Region

#Region "Validate & Save"
    ''' <summary>
    ''' Determines whether this instance is valid.
    ''' </summary>
    ''' <returns>
    ''' <c>true</c> if this instance is valid; otherwise, <c>false</c>.
    ''' </returns>
    Private Function IsValid() As Boolean
        IsValid = True
        If (cboAccountID.Enabled Or cboCustodianID.Enabled) And DataScript.IsExistingAccountAndCustodian(cboAccountID.Text, cboCustodianID.Text) = False Then
            MessageBox.Show("This Account ID / Custodian ID does not exist in the system. Please click Add Account to create the account and then try saving again.", "Account / Custodian Does Not Exist", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation)
            IsValid = False
        ElseIf (cboTicker.Enabled Or cboCusip.Enabled) And DataScript.IsExistingTickerCusip(cboTicker.Text, cboCusip.Text) = False Then
            MessageBox.Show("This Ticker / CUSIP does not exist in the system. Please click Add Security to create the security and then try saving again.", "Ticker / CUSIP Does Not Exist", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation)
            IsValid = False
        End If
    End Function

    ''' <summary>
    ''' Does the save.
    ''' </summary>
    Private Sub DoSave()
        If Not IsValid() Then Exit Sub
        Dim confirm = CurrentConfirm
        If cboAccountID.Enabled Then
            Dim count = Confirms.GetCountWithCustodianID(confirm.ID, confirm.CustodianAccountID)
            Dim result = DialogResult.No
            If count > 0 Then
                Dim message = "There are {0} other unassigned confirms with Custodian ID '{1}'." + Environment.NewLine + "Do you wish to update all of them with the Account ID '{2}'?"
                message = String.Format(message, count, cboCustodianID.Text, cboAccountID.Text)
                result = MessageBox.Show(message, "Update Other Confirms", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)
                If result = DialogResult.Cancel Then Exit Sub
            End If
            Confirms.UpdateWithAccountID(confirm.ID, cboAccountID.Text, result = DialogResult.Yes)
        End If

        If cboCustodianID.Enabled Then
            Dim count = Confirms.GetCountWithAccountID(confirm.ID, confirm.AccountID)
            Dim result = DialogResult.No
            If count > 0 Then
                Dim message = "There are {0} other unassigned confirms with Account ID '{1}'." + Environment.NewLine + "Do you wish to update all of them with the Custodian ID '{2}'?"
                message = String.Format(message, count, cboAccountID.Text, cboCustodianID.Text)
                result = MessageBox.Show(message, "Update Other Confirms", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)
                If result = DialogResult.Cancel Then Exit Sub
            End If
            Confirms.UpdateWithCustodianID(confirm.ID, cboCustodianID.Text, result = DialogResult.Yes)
        End If

        If cboTicker.Enabled Then
            Dim count = Confirms.GetCountWithCusip(confirm.ID, confirm.Cusip)
            Dim result = DialogResult.No
            If count > 0 Then
                Dim message = "There are {0} other unassigned confirms with CUSIP '{1}'." + Environment.NewLine + "Do you wish to update all of them with the Ticker '{2}'?"
                message = String.Format(message, count, cboCusip.Text, cboTicker.Text)
                result = MessageBox.Show(message, "Update Other Confirms", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)
                If result = DialogResult.Cancel Then Exit Sub
            End If
            Confirms.UpdateWithTicker(confirm.ID, cboTicker.Text, result = DialogResult.Yes)
        End If

        If cboCusip.Enabled Then
            Dim count = Confirms.GetCountWithTicker(confirm.ID, confirm.TickerSymbol)
            Dim result = DialogResult.No
            If count > 0 Then
                Dim message = "There are {0} other unassigned confirms with Ticker '{1}'." + Environment.NewLine + "Do you wish to update all of them with the CUSIP '{2}'?"
                message = String.Format(message, count, cboTicker.Text, cboCusip.Text)
                result = MessageBox.Show(message, "Update Other Confirms", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)
                If result = DialogResult.Cancel Then Exit Sub
            End If
            Confirms.UpdateWithCusip(confirm.ID, cboCusip.Text, result = DialogResult.Yes)
        End If
        SyncGrid()
    End Sub
#End Region

#Region "ComboBox Event Handlers"
    'NOTE: It would be best if all four handlers below can be refactored as they all do the same thing.
    '      For now if the logic in one of these handlers changes remember to include it for the others as well to maintain consistency.
    ''' <summary>
    ''' Handles the SelectedIndexChanged event of the cboAccountID control.
    ''' </summary>
    ''' <param name="sender">The source of the event.</param>
    ''' <param name="e">The <see cref="System.EventArgs" /> instance containing the event data.</param>
    Private Sub cboAccountID_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboAccountID.SelectedIndexChanged

        'If user has typed in a value for custodian then don't try do anything smart.
        If cboCustodianID.Enabled And cboCustodianID.Text <> "" And Not _accountsList.Exists(Function(x) x.CustodianID = cboCustodianID.Text) Then Exit Sub

        'Pick the corresponding custodian drop down item for the account the user selected.
        Dim matchingCustodians = _accountsList.FindAll(Function(x) x.AccountID = cboAccountID.Text)
        If matchingCustodians.Count > 0 Then
            If Not matchingCustodians.Exists(Function(x) x.CustodianID = cboCustodianID.Text) Then
                cboCustodianID.Text = matchingCustodians.First().CustodianID
            End If
        End If
    End Sub

    Private Sub cboCustodianID_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboCustodianID.SelectedIndexChanged
        'If user has typed in a value for account then don't try do anything smart.
        If cboAccountID.Enabled And cboAccountID.Text <> "" And Not _accountsList.Exists(Function(x) x.AccountID = cboAccountID.Text) Then Exit Sub

        'Pick the corresponding account drop down item for the custodian the user selected.
        Dim matchingAccounts = _accountsList.FindAll(Function(x) x.CustodianID = cboCustodianID.Text)
        If matchingAccounts.Count > 0 Then
            If Not matchingAccounts.Exists(Function(x) x.AccountID = cboAccountID.Text) Then
                cboAccountID.Text = matchingAccounts.First().AccountID
            End If
        End If

    End Sub

    Private Sub cboTicker_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboTicker.SelectedIndexChanged
        'If user has typed in a value for cusip then don't try do anything smart.
        If cboCusip.Enabled And cboCusip.Text <> "" And Not _securitiesList.Exists(Function(x) x.Cusip = cboCusip.Text) Then Exit Sub

        'Pick the corresponding cusip drop down item for the ticker the user selected.
        Dim matchingSecurities = _securitiesList.FindAll(Function(x) x.Ticker = cboTicker.Text)
        If matchingSecurities.Count > 0 Then
            If Not matchingSecurities.Exists(Function(x) x.Cusip = cboCusip.Text) Then
                cboCusip.Text = matchingSecurities.First().Cusip
            End If
        End If

    End Sub

    Private Sub cboCusip_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboCusip.SelectedIndexChanged
        'If user has typed in a value for cusip then don't try do anything smart.
        If cboTicker.Enabled And cboTicker.Text <> "" And Not _securitiesList.Exists(Function(x) x.Ticker = cboTicker.Text) Then Exit Sub

        'Pick the corresponding ticker drop down item for the cusip the user selected.
        Dim matchingSecurities = _securitiesList.FindAll(Function(x) x.Cusip = cboCusip.Text)
        If matchingSecurities.Count > 0 Then
            If Not matchingSecurities.Exists(Function(x) x.Cusip = cboTicker.Text) Then
                cboTicker.Text = matchingSecurities.First().Ticker
            End If
        End If

    End Sub
#End Region

    Private Sub txtConfirmViewer_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtConfirmViewer.TextChanged

    End Sub

    Private Sub confirmsGrid_CellContentClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles confirmsGrid.CellContentClick

    End Sub

    Private Sub Panel2_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel2.Paint

    End Sub

    Private Sub cboTicker_Leave(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboTicker.Leave
        If cboTicker.Enabled Then
            cboTicker.Text = cboTicker.Text.ToUpper()
        End If
    End Sub
End Class

